<template>
	<div class="page-container">
		<div class="page-loading center-container abs-full"
		     v-show="!loadEnd || loading || securityError">
			<div v-if="parseError">
				<h2 class="text-warning">
					<Icon type="alert-circled"></Icon> 节点解析错误</h2>
			</div>
			<div v-else-if="securityError"
			     class="info-container">
				<h2 class="text-warning">
					<Icon type="alert-circled"></Icon> 访问权限错误
				</h2>
			</div>
			<div v-else>
				<Spin size="large"></Spin>
			</div>
		</div>
		<component v-if="!loading && loadEnd && !parseError && !securityError"
		           :node-code="nodeCode"
		           :is-nf="isNf"
		           :dataset-code="datasetCode"
		           :model="nodeModel"
		           :is="pageComonent()"></component>
	</div>
</template>

<script>
import moduleStore from 'store/type/page';
import loadModel from './model/index';
import moduleBase from 'mixins/storeModule';
import nodeFactory from './nf';
import $ from '@/common';

export default {
	moduleStore,
	mixins: [moduleBase],
	data() {
		return {
			pathModel: '/service/{app}/nf/model/{code}',
			pathDsModel: '/service/{app}/dataset/model/eval/{code}',
			pathCheck: '/service/{app}/security/perm/check/{code}?account_code={account_code}',
			pathRmModel: 'service/{app}/resource_mapping/model/{code}',
			encode: 'page',
			loadEnd: false,
			parseError: false,
			singlePage: false,
			datasetCode: null,
			nodeModel: null,
			nodeCode: null,
			isNf: false,
			securityError: false,
			perm: {},
		};
	},
	methods: {
		pageComonent() {
			return 'nodeFactory';
		},
		updatePageComponent() {
			this.loadingStatus(true);
			this.parseError = false;
			var code = this.$route.params.node;
			this.nodeCode = code;
			this.$store.commit('pushPage', $.nodeList[code]);
			// this.$store.getters.activePageData 查看vuex中的activePage
			// 有没有在缓存的pages中
			var tabPage = this.$store.getters.activePageData;
			//若当前页面在缓存的pages中，且model存在，则给nodeModel赋值
			if (tabPage && tabPage.model) {
				this.$nextTick(() => {
					this.nodeModel = tabPage.model;
					this.loadEnd = true;
					this.loadingStatus(false);
				});
			} else if (!this.singlePage) {
				let code = this.$route.params.node;
				this.loadEnd = false;
				var nodeSetting = $.nodeList[code];
				//判断是否采用本地模型（需在model/index中添加配置）
				//本地没有的model/index中没有的，从后端请求model
				if (nodeSetting && nodeSetting.param.nf_code && !loadModel[code]) {
					this.isNf = true;
					this.datasetCode = nodeSetting.param.dataset_code;
					$.link(this.datasetCode ? this.pathDsModel : this.pathModel, null, {
						param: {
							code: this.datasetCode || nodeSetting.param.nf_code,
						},
					})
						.then(res => {
							if (res.data.model && !res.data.facets) {
								res.data.facets = [{ model: res.data.model }];
							}
							this.nodeModel = res.data;
							this.loadEnd = true;
							this.loadingStatus(false);
						})
						.catch(ex => {
							console.error('model读取错误');
							console.error(ex);
						});
					// nodeSetting中已经缓存了model的，直接使用
				} else if (nodeSetting.param && nodeSetting.param.module) {
					let model = {
						code: nodeSetting.code,
						type: nodeSetting.param.module,
					};
					return new Promise(resolve => {
						this.loadNode(model);
						resolve(model);
					});
					// 否则使用本地文件的modal
				} else {
					return require(['./model/' + code], data => {
						var pageModel = data.default;
						if (pageModel.data && !pageModel.code && pageModel.data.length === 1) {
							pageModel = pageModel.data[0];
						}
						if (pageModel.data && pageModel.status === 1 && !pageModel.code) {
							pageModel = pageModel.data;
						}
						if (pageModel.type !== 'rm') {
							this.loadNode(pageModel);
						} else {
							$.link(this.pathRmModel, null, {
								param: {
									code: pageModel.code,
								},
							}).then(({ data }) => {
								data.type = 'rm';
								this.loadNode(data);
							});
						}
					}).catch(ex => {
						this.parseError = true;
					});
				}
			} else {
				//单独页面加载，定制界面，直接从文件中require
				//使用变量loadEnd标示组件的读取完成状态，在异步加载完成前不予显示
				//loading则用于限制组件名称的加载，当if为true时将会检查组件是否存在，在路由跳转时若为及时将条件改为false，则会报错
				//因此使用两个不同的变量通过分别控制show和if来区分动态元素的加在显示状态和注册状态
				//---替补方案是读取菜单数据，设置所有可能的组件的异步加载属性，异步组件只在用到时加载，只是提前定义并不会真是引用
				this.loadEnd = false;
				this.loadingStatus(true);
				if (this.$options.components[code]) {
					this.loadingStatus(false);
					this.loadEnd = true;
				} else {
					this.$options.components[code] = resolve => {
						this.loadEnd = true;
						return require(['../pages/' + code + '/index'], resolve);
					};
					this.loadingStatus(false);
				}
			}
		},
		// 得到node的model之后，赋值
		loadNode(model) {
			this.$set(this, 'nodeModel', model);
			this.isNf = false;
			this.loadEnd = true;
			this.$nextTick(() => {
				this.loadingStatus(false);
			});
		},
		checkNode(code) {
			this.securityError = false;
			if ($.nodeList[code] && $.nodeList[code].code) {
				if (!$.dev || !$.nodeList[code].dev) {
					//通过app code和节点编码记录节点的访问权限，对重复授权的节点无需再次鉴权
					var encode = `${window.App}_${code}`;
					if (this.perm[encode]) {
						return Promise.resolve().then(() => {
							this.updatePageComponent();
							return true;
						});
					} else {
						return $.link(this.pathCheck, null, {
							param: {
								code: $.nodeList[code].code,
								account_code: this.$store.state.user.account_code,
							},
						}).then(res => {
							if (!res.data) {
								this.securityErrorHandler();
								this.perm[encode] = false;
								return false;
							} else {
								this.updatePageComponent();
								this.perm[encode] = true;
								return true;
							}
						});
					}
				} else if ($.nodeList[code].dev) {
					return new Promise(resolve => {
						this.updatePageComponent();
						resolve(true);
					});
				}
			} else {
				this.securityErrorHandler();
			}
		},
		securityErrorHandler() {
			this.securityError = true;
		},
	},
	beforeRouteUpdate(to, from, next) {
		this.loadingStatus(true);
		next();
		var code = to.params.node;
		this.checkNode(code);
	},
	beforeRouteEnter(to, from, next) {
		next(vm => {
			var code = vm.$route.params.node;
			vm.checkNode(code);
		});
	},
	beforeRouteLeave(to, from, next) {
		this.loadingStatus(true);
		next();
	},
	components: {
		nodeFactory,
	},
};
</script>
